package com.kexilo.system.system.service;

import com.kexilo.core.common.constant.UserConstants;
import com.kexilo.core.common.exception.ServiceException;
import com.kexilo.dict.utils.DictUtils;
import com.kexilo.dict.service.DictService;
import com.kexilo.dict.domain.DictData;
import com.kexilo.core.common.utils.StringUtils;
import com.kexilo.core.system.domain.SysDictData;
import com.kexilo.core.system.domain.SysDictType;
import com.kexilo.system.system.mapper.SysDictDataMapper;
import com.kexilo.system.system.mapper.SysDictTypeMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.annotation.PostConstruct;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 字典 业务层处理
 * 
 * @author Kexilo
 */
@Service
public class SysDictTypeServiceImpl implements ISysDictTypeService {
    
    private static final Logger log = LoggerFactory.getLogger(SysDictTypeServiceImpl.class);
    
    @Autowired
    private SysDictTypeMapper dictTypeMapper;

    @Autowired
    private SysDictDataMapper dictDataMapper;

    @Autowired
    private ISysDictDataService dictDataService;
    
    @Autowired(required = false)
    private DictService dictService;

    /**
     * 项目启动时，初始化字典到缓存
     */
    @PostConstruct
    public void init() {
        loadingDictCache();
    }

    /**
     * 根据条件分页查询字典类型
     * 
     * @param dictType 字典类型信息
     * @return 字典类型集合信息
     */
    @Override
    public List<SysDictType> selectDictTypeList(SysDictType dictType) {
        return dictTypeMapper.selectDictTypeList(dictType);
    }

    /**
     * 根据所有字典类型
     * 
     * @return 字典类型集合信息
     */
    @Override
    @Cacheable(value = "dict:types", key = "'all'")
    public List<SysDictType> selectDictTypeAll() {
        return dictTypeMapper.selectDictTypeAll();
    }

    /**
     * 根据字典类型ID查询信息
     * 
     * @param dictId 字典类型ID
     * @return 字典类型
     */
    @Override
    @Cacheable(value = "dict:type", key = "#dictId", condition = "#dictId != null && #dictId > 0")
    public SysDictType selectDictTypeById(Long dictId) {
        return dictTypeMapper.selectDictTypeById(dictId);
    }

    /**
     * 根据字典类型查询信息
     * 
     * @param dictType 字典类型
     * @return 字典类型
     */
    @Override
    @Cacheable(value = "dict:type:byname", key = "#dictType", condition = "#dictType != null")
    public SysDictType selectDictTypeByType(String dictType) {
        return dictTypeMapper.selectDictTypeByType(dictType);
    }

    /**
     * 批量删除字典类型信息
     * 
     * @param dictIds 需要删除的字典ID
     */
    @Override
    @CacheEvict(value = {"dict:types", "dict:type", "dict:type:byname", "dict:data"}, allEntries = true)
    public void deleteDictTypeByIds(Long[] dictIds) {
        for (Long dictId : dictIds) {
            SysDictType dictType = selectDictTypeById(dictId);
            if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0) {
                throw new ServiceException(String.format("%1$s已分配,不能删除", dictType.getDictName()));
            }
            dictTypeMapper.deleteDictTypeById(dictId);
            DictUtils.removeDictCache(dictType.getDictType());
        }
    }

    /**
     * 加载参数缓存数据
     */
    @Override
    public void loadingDictCache() {
        // 获取所有字典类型，然后逐个加载到缓存
        List<SysDictType> dictTypes = selectDictTypeList(new SysDictType());
        for (SysDictType dictType : dictTypes) {
            try {
                // 从数据库获取字典数据
                List<SysDictData> sysDictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
                if (sysDictDatas != null && !sysDictDatas.isEmpty()) {
                    // 转换为dict插件的DictData格式并缓存
                    List<DictData> dictDatas = convertToDictData(sysDictDatas);
                    DictUtils.setDictCache(dictType.getDictType(), dictDatas);
                }
            } catch (Exception e) {
                log.warn("加载字典缓存失败: {}", dictType.getDictType(), e);
            }
        }
    }

    /**
     * 清空字典缓存数据
     */
    @Override
    public void clearDictCache() {
        DictUtils.clearDictCache();
    }
    
    /**
     * 将SysDictData转换为DictData
     * 
     * @param sysDictDatas 系统字典数据列表
     * @return 字典数据列表
     */
    private List<DictData> convertToDictData(List<SysDictData> sysDictDatas) {
        if (sysDictDatas == null || sysDictDatas.isEmpty()) {
            return new java.util.ArrayList<>();
        }
        
        return sysDictDatas.stream().map(this::convertToDictData).collect(java.util.stream.Collectors.toList());
    }
    
    /**
     * 将单个SysDictData转换为DictData
     * 
     * @param sysDictData 系统字典数据
     * @return 字典数据
     */
    private DictData convertToDictData(SysDictData sysDictData) {
        if (sysDictData == null) {
            return null;
        }
        
        DictData dictData = new DictData();
        dictData.setDictCode(sysDictData.getDictCode());
        dictData.setDictSort(sysDictData.getDictSort());
        dictData.setDictLabel(sysDictData.getDictLabel());
        dictData.setDictValue(sysDictData.getDictValue());
        dictData.setDictType(sysDictData.getDictType());
        dictData.setCssClass(sysDictData.getCssClass());
        dictData.setListClass(sysDictData.getListClass());
        dictData.setIsDefault(sysDictData.getIsDefault());
        dictData.setStatus(sysDictData.getStatus());
        dictData.setRemark(sysDictData.getRemark());
        dictData.setCreateBy(sysDictData.getCreateBy());
        dictData.setCreateTime(sysDictData.getCreateTime());
        dictData.setUpdateBy(sysDictData.getUpdateBy());
        dictData.setUpdateTime(sysDictData.getUpdateTime());
        
        return dictData;
    }

    /**
     * 重置字典缓存数据
     */
    @Override
    public void resetDictCache() {
        clearDictCache();
        loadingDictCache();
    }

    /**
     * 新增保存字典类型信息
     * 
     * @param dictType 字典类型信息
     * @return 结果
     */
    @Override
    @CacheEvict(value = {"dict:types", "dict:type", "dict:type:byname"}, allEntries = true)
    public int insertDictType(SysDictType dictType) {
        int row = dictTypeMapper.insertDictType(dictType);
        if (row > 0) {
            DictUtils.setDictCache(dictType.getDictType(), null);
        }
        return row;
    }

    /**
     * 修改保存字典类型信息
     * 
     * @param dictType 字典类型信息
     * @return 结果
     */
    @Override
    @Transactional
    @CacheEvict(value = {"dict:types", "dict:type", "dict:type:byname", "dict:data"}, allEntries = true)
    public int updateDictType(SysDictType dictType) {
        SysDictType oldDict = dictTypeMapper.selectDictTypeById(dictType.getDictId());
        dictDataMapper.updateDictDataType(oldDict.getDictType(), dictType.getDictType());
        int row = dictTypeMapper.updateDictType(dictType);
        if (row > 0) {
            try {
                // 更新缓存：重新从数据库加载字典数据
                List<SysDictData> sysDictDatas = dictDataMapper.selectDictDataByType(dictType.getDictType());
                if (sysDictDatas != null && !sysDictDatas.isEmpty()) {
                    // 转换为dict插件的DictData格式并缓存
                    List<DictData> dictDatas = convertToDictData(sysDictDatas);
                    DictUtils.setDictCache(dictType.getDictType(), dictDatas);
                }
            } catch (Exception e) {
                log.warn("更新字典缓存失败: {}", dictType.getDictType(), e);
            }
        }
        return row;
    }

    /**
     * 校验字典类型称是否唯一
     * 
     * @param dictType 字典类型信息
     * @return 结果
     */
    @Override
    public boolean checkDictTypeUnique(SysDictType dictType) {
        Long dictId = StringUtils.isNull(dictType.getDictId()) ? -1L : dictType.getDictId();
        SysDictType info = dictTypeMapper.checkDictTypeUnique(dictType.getDictType(), dictId);
        if (StringUtils.isNotNull(info) && info.getDictId().longValue() != dictId.longValue()) {
            return false; // NOT_UNIQUE
        }
        return true; // UNIQUE
    }
}
